﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Printing;
using System.IO;
using System.Windows.Forms;
using MPMovieCatalog.Configuration;
using MPMovieCatalog.Configuration.Sections;
using MPMovieCatalog.Domain;
using MPMovieCatalog.Forms.Grid;
using MPMovieCatalog.Service;
using MPMovieCatalog.Util;
using MPMovieCatalog.Export.Forms;

namespace MPMovieCatalog.Forms
{
    public partial class ApplicationForm : Form
    {
        public ApplicationForm()
        {
            InitializeComponent();

            ConfigurationWrapper wrapper = new ConfigurationWrapper();
            ResourceUtils.SetCurrentLanguage(wrapper.GUISection.Language);

            foreach (LanguageFile languageFile in ResourceUtils.GetLanguages())
            {
                ToolStripMenuItem menuItem = new ToolStripMenuItem(languageFile.Language);
                menuItem.Click += new EventHandler(ChangeLanguage);
                languageMenuItem.DropDownItems.Add(menuItem);

                if (languageFile.Language == ResourceUtils.GetCurrentLanguage())
                {
                    menuItem.Checked = true;
                }
            }

            string currentTemplateName = TemplateUtils.GetCurrentViewTemplateName();
            foreach (Template template in TemplateUtils.FindAllTemplates(TemplateType.View, false))
            {
                ToolStripMenuItem menuItem = new ToolStripMenuItem(template.Description);
                menuItem.Tag = template.Name;

                menuItem.Click += new EventHandler(ChangeTemplate);
                templatesMenuItem.DropDownItems.Add(menuItem);

                if (template.Name == currentTemplateName)
                {
                    menuItem.Checked = true;
                }
            }

            UpdateUI();
        }

        private void ApplicationForm_Load(object sender, EventArgs e)
        {
            LoadSettings();
            RefreshList();
        }

        private void exitMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void movieGrid_SelectionChanged(object sender, EventArgs e)
        {
            int selectionCount = movieGrid.SelectedRows.Count;

            editToolButton.Enabled = selectionCount > 0;
            deleteToolButton.Enabled = selectionCount > 0;

            editContextMenuItem.Enabled = selectionCount > 0;
            deleteContextMenuItem.Enabled = selectionCount > 0;

            selectedCountLabel.Text = string.Format(ResourceUtils.GetString("main", 20), selectionCount, bindingSource.Count.ToString());

            ShowMovieInfo();
        }

        private void RefreshList()
        {
            Cursor = Cursors.WaitCursor;
            if (MovieServiceFactory.IsInitialized)
            {
                IBindingList oldDatasorce = bindingSource.DataSource as IBindingList;
                IBindingList newDatasource = new SortableBindingList<MovieInfo>(MovieServiceFactory.getMovieService().FindMovieInfoByIds(null));

                bindingSource.DataSource = newDatasource;
                if (oldDatasorce != null && oldDatasorce.IsSorted)
                {
                    newDatasource.ApplySort(oldDatasorce.SortProperty, oldDatasorce.SortDirection);
                }

                movieCountLabel.Text = string.Format(ResourceUtils.GetString("main", 6), bindingSource.Count.ToString());
            }
            Cursor = Cursors.Arrow;
        }


        private void LoadSettings()
        {
            ConfigurationWrapper configurationWrapper = new ConfigurationWrapper();
            ConnectionSection connectionSection = configurationWrapper.ConnectionSection;
            try
            {
                MovieServiceFactory.Initialize(connectionSection.Host, connectionSection.Port);
            }
            catch
            {
                MessageBox.Show(this, ResourceUtils.GetString("main", 7), ResourceUtils.GetString("common", 0), MessageBoxButtons.OK, MessageBoxIcon.Error);
                bindingSource.DataSource = null;
            }
        }

        public void AddMovie(object sender, EventArgs e)
        {
            using (EditForm editForm = new EditForm())
            {
                IMovieService movieService = MovieServiceFactory.getMovieService();
                editForm.AvailableGenres = movieService.FindAvailableGenres(0);
                editForm.AvailableActors = movieService.FindAvailableActors(0);
                editForm.Data = new MovieInfo();
                if (editForm.ShowDialog(this) == DialogResult.OK)
                {
                    MovieInfo movieInfo = editForm.Data;
                    movieInfo.Picture = File.Exists(movieInfo.PictureFileName) ? Convert.ToBase64String(File.ReadAllBytes(movieInfo.PictureFileName)) : null;
                    long movieId = movieService.InsertMovieInfo(movieInfo);

                    bindingSource.Add(movieService.FindMovieInfoById(movieId));
                }
            }
        }

        public void EditMovie(object sender, EventArgs e)
        {
            NamedEntity namedEntity = (NamedEntity)bindingSource.Current;

            IMovieService movieService = MovieServiceFactory.getMovieService();
            MovieInfo movieInfo = movieService.FindMovieInfoById(namedEntity.Id);
            if (movieInfo != null && movieInfo.Picture != null && movieInfo.Picture != string.Empty)
            {
                movieInfo.PictureFileName = Utils.GetTempFileName();
                File.WriteAllBytes(movieInfo.PictureFileName, Convert.FromBase64String(movieInfo.Picture));
            }

            using (EditForm editForm = new EditForm())
            {
                editForm.AvailableGenres = movieService.FindAvailableGenres(namedEntity.Id);
                editForm.AvailableActors = movieService.FindAvailableActors(namedEntity.Id);
                editForm.Data = movieInfo;
                if (editForm.ShowDialog(this) == DialogResult.OK)
                {
                    MovieInfo updatedMovieInfo = editForm.Data;
                    bool updatePicture = movieInfo.PictureFileName != updatedMovieInfo.PictureFileName || movieInfo.Name != updatedMovieInfo.Name;
                    updatedMovieInfo.Picture = updatePicture && File.Exists(updatedMovieInfo.PictureFileName) ? Convert.ToBase64String(File.ReadAllBytes(updatedMovieInfo.PictureFileName)) : null;
                    movieService.UpdateMovieInfo(updatedMovieInfo, updatePicture);

                    movieInfo = movieService.FindMovieInfoById(movieInfo.Id);
                    int pos = bindingSource.Position;
                    bindingSource.RemoveCurrent();
                    if (pos < bindingSource.Count)
                    {
                        bindingSource.Insert(pos, movieInfo);
                    }
                    else
                    {
                        bindingSource.Add(movieInfo);
                    }
                    bindingSource.Position = pos;
                    ShowMovieInfo();
                }
            }
        }

        public void DeleteMovie(object sender, EventArgs e)
        {
            MovieInfo movieInfo = (MovieInfo)bindingSource.Current;
            if (MessageBox.Show(string.Format(ResourceUtils.GetString("main", 8), movieInfo.Name), ResourceUtils.GetString("common", 1), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                MovieServiceFactory.getMovieService().DeleteMovieInfo(movieInfo);
                bindingSource.RemoveCurrent();
            }
        }

        public void ChangeSettings(object sender, EventArgs e)
        {
            using (ConfigurationForm settingForm = new ConfigurationForm())
            {
                if (settingForm.ShowDialog() == DialogResult.OK)
                {
                    settingForm.SaveSettings();
                    LoadSettings();
                    RefreshList();
                }
            }
        }

        public void ShowMovieInfo()
        {
            browser.DocumentText = "";

            if (bindingSource.Current == null) return;

            try
            {
                MovieInfo movieInfo = (MovieInfo)bindingSource.Current;
                browser.DocumentText = TemplateUtils.TransformMovie(movieInfo, null);
            }
            catch
            {
                MessageBox.Show(this, ResourceUtils.GetString("main", 14), ResourceUtils.GetString("common", 0), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void EditMovie(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                EditMovie(sender, (EventArgs)e);
            }
        }

        private void ApplicationForm_Shown(object sender, EventArgs e)
        {
            ShowMovieInfo();
        }

        private void RefreshList(object sender, EventArgs e)
        {
            RefreshList();
        }

        private void ApplicationForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            SortedList sortedColumns = new SortedList();
            foreach (DataGridViewColumn gridColumn in movieGrid.Columns)
            {
                Field field = Fields.FindFieldByName(gridColumn.Name);
                if (field != null)
                {
                    sortedColumns.Add(gridColumn.DisplayIndex, new Column(field, gridColumn.Width));
                }
            }

            ConfigurationWrapper wrapper = new ConfigurationWrapper();
            wrapper.GUISection.Columns = new ArrayList(sortedColumns.Values);
            wrapper.SaveConfiguration();

            MPMovieCatalog.Util.Utils.DeleteTempFiles();
        }

        private void UpdateUI()
        {
            fileMenuItem.Text = ResourceUtils.GetString("main", 0);
            exitMenuItem.Text = ResourceUtils.GetString("main", 1);
            printMenuItem.Text = ResourceUtils.GetString("main", 15);
            exportMenuItem.Text = ResourceUtils.GetString("main", 16);
            exportTextMenuItem.Text = ResourceUtils.GetString("main", 17);
            exportHTMLMenuItem.Text = ResourceUtils.GetString("main", 18);
            exportAMCMenuItem.Text = ResourceUtils.GetString("main", 19);
            viewMenuItem.Text = ResourceUtils.GetString("main", 23); ;
            columnsMenuItem.Text = ResourceUtils.GetString("main", 21); ;
            refreshMenuItem.Text = ResourceUtils.GetString("main", 12);
            toolsMenuItem.Text = ResourceUtils.GetString("main", 2); ;
            listsMenuItem.Text = ResourceUtils.GetString("main", 24); ;
            languageMenuItem.Text = ResourceUtils.GetString("main", 3); ;
            settingsMenuItem.Text = ResourceUtils.GetString("main", 4); ;
            titleColumn.HeaderText = ResourceUtils.GetString("main", 5); ;
            movieCountLabel.Text = string.Format(ResourceUtils.GetString("main", 6), bindingSource.Count.ToString());
            selectedCountLabel.Text = string.Format(ResourceUtils.GetString("main", 20), movieGrid.SelectedRows.Count, bindingSource.Count.ToString());

            refreshButton.ToolTipText = ResourceUtils.GetString("main", 12);
            addTtoolButton.ToolTipText = ResourceUtils.GetString("main", 9);
            editToolButton.ToolTipText = ResourceUtils.GetString("main", 10);
            deleteToolButton.ToolTipText = ResourceUtils.GetString("main", 11);
            columnsToolButton.ToolTipText = ResourceUtils.GetString("main", 21);
            optionsToolButton.ToolTipText = ResourceUtils.GetString("main", 4);
            importFilesToolButton.ToolTipText = ResourceUtils.GetString("main", 4);

            addContextMenuItem.Text = ResourceUtils.GetString("main", 9);
            editContextMenuItem.Text = ResourceUtils.GetString("main", 10);
            deleteContextMenuItem.Text = ResourceUtils.GetString("main", 11);
            columnsContextMenuItem.Text = ResourceUtils.GetString("main", 25);

            templatesMenuItem.Text = ResourceUtils.GetString("main", 13);

            UpdateMovieGrid();
        }

        private void ChangeLanguage(object sender, EventArgs e)
        {
            ToolStripMenuItem currentLanguageMenuItem = sender as ToolStripMenuItem;
            if (!currentLanguageMenuItem.Checked)
            {
                ConfigurationWrapper wrapper = new ConfigurationWrapper();
                wrapper.GUISection.Language = currentLanguageMenuItem.Text;
                wrapper.SaveConfiguration();

                foreach (ToolStripMenuItem menuItem in languageMenuItem.DropDownItems)
                {
                    menuItem.Checked = false;
                }
                currentLanguageMenuItem.Checked = true;

                ResourceUtils.SetCurrentLanguage(currentLanguageMenuItem.Text);
                UpdateUI();
                ShowMovieInfo();
            }
        }

        private void ChangeTemplate(object sender, EventArgs e)
        {
            ToolStripMenuItem currentTemplateMenuItem = sender as ToolStripMenuItem;
            if (!currentTemplateMenuItem.Checked)
            {
                ConfigurationWrapper wrapper = new ConfigurationWrapper();
                wrapper.GUISection.Template = currentTemplateMenuItem.Tag as string;
                wrapper.SaveConfiguration();

                foreach (ToolStripMenuItem menuItem in templatesMenuItem.DropDownItems)
                {
                    menuItem.Checked = false;
                }
                currentTemplateMenuItem.Checked = true;

                ShowMovieInfo();
            }
        }

        private void printMenuItem_Click(object sender, EventArgs e)
        {
            using (PrintForm printForm = new PrintForm())
            {
                ArrayList selectedMovies = new ArrayList();
                foreach (DataGridViewRow row in movieGrid.SelectedRows)
                {
                    selectedMovies.Add(row.DataBoundItem);
                }
                printForm.SelectedMovies = selectedMovies;
                printForm.AllMoviesCount = bindingSource.Count;
                printForm.ShowDialog(this);
            }
        }

        private void exportTextMenuItem_Click(object sender, EventArgs e)
        {
            using (TextExportForm textExportForm = new TextExportForm())
            {
                ArrayList selectedMovies = new ArrayList();
                foreach (DataGridViewRow row in movieGrid.SelectedRows)
                {
                    selectedMovies.Add(row.DataBoundItem);
                }
                textExportForm.SelectedMovies = selectedMovies;
                textExportForm.AllMoviesCount = bindingSource.Count;
                textExportForm.ShowDialog(this);
            }
        }

        private void exportAMCMenuItem_Click(object sender, EventArgs e)
        {
            using (AMCExportForm amcExportForm = new AMCExportForm())
            {
                ArrayList selectedMovies = new ArrayList();
                foreach (DataGridViewRow row in movieGrid.SelectedRows)
                {
                    selectedMovies.Add(row.DataBoundItem);
                }
                amcExportForm.SelectedMovies = selectedMovies;
                amcExportForm.AllMoviesCount = bindingSource.Count;
                amcExportForm.ShowDialog(this);
            }
        }

        private void exportHTMLMenuItem_Click(object sender, EventArgs e)
        {
            using (HTMLExportForm htmlExportForm = new HTMLExportForm())
            {
                ArrayList selectedMovies = new ArrayList();
                foreach (DataGridViewRow row in movieGrid.SelectedRows)
                {
                    selectedMovies.Add(row.DataBoundItem);
                }
                htmlExportForm.SelectedMovies = selectedMovies;
                htmlExportForm.AllMoviesCount = bindingSource.Count;
                htmlExportForm.ShowDialog(this);
            }
        }

        private void columnsButton_Click(object sender, EventArgs e)
        {
            using (FieldsForm fieldsForm = new FieldsForm())
            {
                fieldsForm.Text = ResourceUtils.GetString("main", 22);

                ConfigurationWrapper wrapper = new ConfigurationWrapper();

                SortedList fields = new SortedList();
                foreach (DataGridViewColumn gridColumn in movieGrid.Columns)
                {
                    Field field = Fields.FindFieldByName(gridColumn.Name);
                    if (field != null)
                    {
                        fields.Add(gridColumn.DisplayIndex, field);
                    }
                }

                fieldsForm.SelectedFields = new ArrayList(fields.Values);

                if (fieldsForm.ShowDialog(this) == DialogResult.OK)
                {
                    ArrayList columns = new ArrayList();
                    foreach (Field field in fieldsForm.SelectedFields)
                    {
                        columns.Add(new Column(field, 0));
                    }

                    wrapper.GUISection.Columns = columns;
                    wrapper.SaveConfiguration();
                    UpdateMovieGrid();
                }
            }
        }

        private void UpdateMovieGrid()
        {
            movieGrid.Columns.Clear();

            ConfigurationWrapper wrapper = new ConfigurationWrapper();
            foreach (Column column in wrapper.GUISection.Columns)
            {
            	DataGridViewColumn gridColumn = null;
            	if (column.Field is BooleanField)
            	{
            		gridColumn = new DataGridViewCheckBoxColumn();
            	}
            	else
            	{
            		gridColumn = new DataGridViewTextBoxColumn();
            	}
            		
                gridColumn.HeaderText = column.Field.DisplayName;
                gridColumn.Name = column.Field.Name;
                gridColumn.ReadOnly = true;
                gridColumn.HeaderCell.Style.WrapMode = DataGridViewTriState.False;
                gridColumn.DefaultCellStyle.Format = column.Field.Format;
                gridColumn.DataPropertyName = column.DataPropertyName;

                if (column.Width > 0)
                {
                    gridColumn.Width = column.Width;
                }

                movieGrid.Columns.Add(gridColumn);
            }
        }

        private void movieGrid_ColumnDividerDoubleClick(object sender, DataGridViewColumnDividerDoubleClickEventArgs e)
        {
            movieGrid.Columns[e.ColumnIndex].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            movieGrid.InvalidateColumn(e.ColumnIndex);

            movieGrid.Columns[e.ColumnIndex].AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet;
            movieGrid.InvalidateColumn(e.ColumnIndex);
        }

        private void listsMenuItem_Click(object sender, EventArgs e)
        {
            using (ReferenceForm referenceForm = new ReferenceForm())
            {
                referenceForm.ShowDialog(this);
            }

        }

        private void movieGrid_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                e.Handled = true;
                EditMovie(sender, e);
            }
        }
        
        void ImportFiles(object sender, EventArgs e)
        {
        	using(ImportFilesForm importFilesForm =  new ImportFilesForm())
        	{
        		IMovieService movieService = MovieServiceFactory.getMovieService();
        		importFilesForm.Files = movieService.GetNewFiles();
        		
        		importFilesForm.ShowDialog(this);
                RefreshList();
        	}
        }
    }
}